package com.learn.io.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author wangxing
 * @version 2020/7/30 8:44 Administrator
 */
public class NettyServer {
    static Logger logger = LoggerFactory.getLogger(NettyServer.class);

    public static ServerBootstrap newServerBootstrap(EventLoopGroup bossGroup, EventLoopGroup workerGroup,
                                                     ChannelHandler channelHandler) {
        ServerBootstrap bootstrap = new ServerBootstrap();
//        使用链式编程配置参数
//        设置两个线程组ServerBootstrap
        bootstrap.group(bossGroup, workerGroup)
//                使用NioServerSocketChannel作为服务器通道实现
                .channel(NioServerSocketChannel.class)
//                初始化服务器连接队列大小，服务端处理客户端请求是顺序处理，所以同一时间只能处理一个客户端连接
//                多客户端同时来到，服务端将不能处理的客户端请求放入到队列中等待
                .option(ChannelOption.SO_BACKLOG, 1024)
//                创建通道初始化对象，设置初始化参数
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline channelPipeline = socketChannel.pipeline();
//                        编解码
//                        向pipeline中加入解码器
                        channelPipeline.addLast("decoder", new StringDecoder());
//                        向pipeline中加入编码器
                        channelPipeline.addLast("encode", new StringEncoder());
//                对workerGroup的SocketChannel设置自定义处理器
                        channelPipeline.addLast((channelHandler));
                    }
                });
        return bootstrap;
    }

    public static void main(String[] args) throws InterruptedException {
//        设置线程组,一个管理连接创建
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
//        一个管理消息读取,发送工作线程组
        EventLoopGroup workerGroup = new NioEventLoopGroup(10);
//        server
        ServerBootstrap bootstrap = newServerBootstrap(bossGroup, workerGroup, new CharNettyServerHandler());
        int port = 9009;
        System.out.println("netty server start ");
//        启动服务器,并绑定端口,bind是异步操作,sync方法是等待异步操作执行完毕
        ChannelFuture channelFuture = bootstrap.bind(port).sync();
//        设置监听器,监听我们关注的事情
        channelFuture.addListener((ChannelFutureListener) future -> {
            if (channelFuture.isSuccess()) {
                logger.info("监听端口{}成功", port);
            } else {
                logger.info("监听端口{}失败", port);
            }
            if (channelFuture.isDone()) {
                logger.info("任务完成了");
            }
            if (channelFuture.isCancelled()) {
                logger.info("任务被取消了");
            }
        });
//        对通道关闭进行监听，closeFuture是异步操作，监听通道关闭
//        通过sync方法同步等待通道关闭处理完毕，这里会阻塞等待通道关闭完成
        channelFuture.channel().closeFuture().sync();
//        释放线程组资源
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}
